﻿using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.CharacterDevelopment;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Roster;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using TaleWorlds.SaveSystem;

namespace TaleWorlds.CampaignSystem.MapEvents
{
	// Token: 0x020002BD RID: 701
	public class RaidEventComponent : MapEventComponent
	{
		// Token: 0x06002991 RID: 10641 RVA: 0x000B27DA File Offset: 0x000B09DA
		internal static void AutoGeneratedStaticCollectObjectsRaidEventComponent(object o, List<object> collectedObjects)
		{
			((RaidEventComponent)o).AutoGeneratedInstanceCollectObjects(collectedObjects);
		}

		// Token: 0x06002992 RID: 10642 RVA: 0x000B27E8 File Offset: 0x000B09E8
		protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
		{
			base.AutoGeneratedInstanceCollectObjects(collectedObjects);
			collectedObjects.Add(this._raidProductionRewards);
		}

		// Token: 0x06002993 RID: 10643 RVA: 0x000B27FD File Offset: 0x000B09FD
		internal static object AutoGeneratedGetMemberValueRaidDamage(object o)
		{
			return ((RaidEventComponent)o).RaidDamage;
		}

		// Token: 0x06002994 RID: 10644 RVA: 0x000B280F File Offset: 0x000B0A0F
		internal static object AutoGeneratedGetMemberValue_nextSettlementDamage(object o)
		{
			return ((RaidEventComponent)o)._nextSettlementDamage;
		}

		// Token: 0x06002995 RID: 10645 RVA: 0x000B2821 File Offset: 0x000B0A21
		internal static object AutoGeneratedGetMemberValue_lootedItemCount(object o)
		{
			return ((RaidEventComponent)o)._lootedItemCount;
		}

		// Token: 0x06002996 RID: 10646 RVA: 0x000B2833 File Offset: 0x000B0A33
		internal static object AutoGeneratedGetMemberValue_raidProductionRewards(object o)
		{
			return ((RaidEventComponent)o)._raidProductionRewards;
		}

		// Token: 0x17000A67 RID: 2663
		// (get) Token: 0x06002997 RID: 10647 RVA: 0x000B2840 File Offset: 0x000B0A40
		// (set) Token: 0x06002998 RID: 10648 RVA: 0x000B2848 File Offset: 0x000B0A48
		[SaveableProperty(20)]
		public float RaidDamage { get; private set; }

		// Token: 0x17000A68 RID: 2664
		// (get) Token: 0x06002999 RID: 10649 RVA: 0x000B2851 File Offset: 0x000B0A51
		public MapEventSide DefenderSide
		{
			get
			{
				return base.MapEvent.DefenderSide;
			}
		}

		// Token: 0x17000A69 RID: 2665
		// (get) Token: 0x0600299A RID: 10650 RVA: 0x000B285E File Offset: 0x000B0A5E
		public MapEventSide AttackerSide
		{
			get
			{
				return base.MapEvent.AttackerSide;
			}
		}

		// Token: 0x17000A6A RID: 2666
		// (get) Token: 0x0600299B RID: 10651 RVA: 0x000B286B File Offset: 0x000B0A6B
		public Settlement MapEventSettlement
		{
			get
			{
				return base.MapEvent.MapEventSettlement;
			}
		}

		// Token: 0x17000A6B RID: 2667
		// (get) Token: 0x0600299C RID: 10652 RVA: 0x000B2878 File Offset: 0x000B0A78
		public bool IsPlayerMapEvent
		{
			get
			{
				return base.MapEvent.IsPlayerMapEvent;
			}
		}

		// Token: 0x17000A6C RID: 2668
		// (get) Token: 0x0600299D RID: 10653 RVA: 0x000B2885 File Offset: 0x000B0A85
		public BattleState BattleState
		{
			get
			{
				return base.MapEvent.BattleState;
			}
		}

		// Token: 0x0600299E RID: 10654 RVA: 0x000B2892 File Offset: 0x000B0A92
		protected RaidEventComponent(MapEvent mapEvent) : base(mapEvent)
		{
		}

		// Token: 0x0600299F RID: 10655 RVA: 0x000B28A8 File Offset: 0x000B0AA8
		public static RaidEventComponent CreateRaidEvent(PartyBase attackerParty, PartyBase defenderParty)
		{
			MapEvent mapEvent = new MapEvent();
			RaidEventComponent raidEventComponent = new RaidEventComponent(mapEvent);
			mapEvent.Initialize(attackerParty, defenderParty, raidEventComponent, MapEvent.BattleTypes.Raid);
			Settlement settlement = defenderParty.Settlement;
			if (((settlement != null) ? settlement.MilitiaPartyComponent : null) != null)
			{
				defenderParty.Settlement.MilitiaPartyComponent.MobileParty.MapEventSide = mapEvent.DefenderSide;
			}
			Campaign.Current.MapEventManager.OnMapEventCreated(mapEvent);
			return raidEventComponent;
		}

		// Token: 0x060029A0 RID: 10656 RVA: 0x000B290C File Offset: 0x000B0B0C
		public static RaidEventComponent CreateComponentForOldSaves(MapEvent mapEvent, float nextSettlementDamage, int lootedItemCount, float raidDamage)
		{
			return new RaidEventComponent(mapEvent)
			{
				_nextSettlementDamage = nextSettlementDamage,
				_lootedItemCount = lootedItemCount,
				RaidDamage = raidDamage
			};
		}

		// Token: 0x060029A1 RID: 10657 RVA: 0x000B292C File Offset: 0x000B0B2C
		protected override void OnInitialize()
		{
			this._nextSettlementDamage = 0f;
			this.RaidDamage = 0f;
			ChangeVillageStateAction.ApplyBySettingToBeingRaided(this.MapEventSettlement, this.AttackerSide.LeaderParty.MobileParty);
			if (this._raidProductionRewards == null)
			{
				this._raidProductionRewards = new Dictionary<ItemObject, float>();
				return;
			}
			this._raidProductionRewards.Clear();
		}

		// Token: 0x060029A2 RID: 10658 RVA: 0x000B298C File Offset: 0x000B0B8C
		protected override void OnFinalize()
		{
			if (this.DefenderSide.Parties.Count <= 1)
			{
				CampaignEventDispatcher.Instance.RaidCompleted((this.BattleState == BattleState.AttackerVictory) ? BattleSideEnum.Attacker : BattleSideEnum.Defender, this);
			}
			if (this.MapEventSettlement.SettlementHitPoints > 0f)
			{
				ChangeVillageStateAction.ApplyBySettingToNormal(this.MapEventSettlement);
			}
			if (this._raidProductionRewards != null)
			{
				this._raidProductionRewards.Clear();
			}
		}

		// Token: 0x060029A3 RID: 10659 RVA: 0x000B29F4 File Offset: 0x000B0BF4
		internal override void Finish()
		{
			Settlement mapEventSettlement = this.MapEventSettlement;
			float? num = (mapEventSettlement != null) ? new float?(mapEventSettlement.SettlementHitPoints) : null;
			double? num2 = (num != null) ? new double?((double)num.GetValueOrDefault()) : null;
			double num3 = 1E-05;
			if (num2.GetValueOrDefault() <= num3 & num2 != null)
			{
				ChangeVillageStateAction.ApplyBySettingToLooted(this.MapEventSettlement, this.AttackerSide.LeaderParty.MobileParty);
			}
			if (this.IsPlayerMapEvent && PlayerEncounter.Current != null)
			{
				PlayerEncounter.Current.FinishRaid();
			}
		}

		// Token: 0x060029A4 RID: 10660 RVA: 0x000B2A9C File Offset: 0x000B0C9C
		internal override void Update(ref bool finish)
		{
			if (this.DefenderSide.TroopCount == 0)
			{
				this._nextSettlementDamage += Campaign.Current.Models.RaidModel.CalculateHitDamage(this.AttackerSide, this.MapEventSettlement.SettlementHitPoints);
				if ((double)this._nextSettlementDamage > 0.05)
				{
					float num = -1f;
					if (this.MapEventSettlement.IsVillage)
					{
						num = this._nextSettlementDamage * 0.5f * this.MapEventSettlement.Village.Hearth;
						this.MapEventSettlement.Village.Hearth -= num;
						Hero leaderHero = this.AttackerSide.LeaderParty.LeaderHero;
						if (leaderHero != null)
						{
							int num2 = (int)(num * (float)Campaign.Current.Models.RaidModel.GoldRewardForEachLostHearth);
							if (num2 > 0)
							{
								if (leaderHero == Hero.MainHero)
								{
									TextObject textObject = GameTexts.FindText("str_plunder_gain_message", null);
									textObject.SetTextVariable("GOLD", num2);
									MBInformationManager.AddQuickInformation(textObject, 0, null, "");
								}
								GiveGoldAction.ApplyBetweenCharacters(null, leaderHero, num2, true);
							}
						}
					}
					this.MapEventSettlement.SettlementHitPoints -= this._nextSettlementDamage;
					this.RaidDamage += this._nextSettlementDamage;
					this.RaidDamage = MathF.Min(this.RaidDamage, 1f);
					int num3 = 0;
					foreach (MapEventParty mapEventParty in this.AttackerSide.Parties)
					{
						num3 += mapEventParty.Party.MemberRoster.TotalManCount;
					}
					if (num3 > 0)
					{
						float nextSettlementDamage = this._nextSettlementDamage;
						int num4 = 0;
						foreach (ItemRosterElement itemRosterElement in this.MapEventSettlement.ItemRoster)
						{
							num4 += itemRosterElement.Amount;
						}
						ItemRoster itemRoster = new ItemRoster();
						PartyBase partyBase = this.AttackerSide.LeaderParty;
						if (num4 > 0)
						{
							int num5 = MBRandom.RoundRandomized((float)num4 * nextSettlementDamage);
							if (num5 > num4)
							{
								num5 = num4;
							}
							EquipmentElement rosterElement = this.MapEventSettlement.ItemRoster.First<ItemRosterElement>().EquipmentElement;
							for (int i = 0; i < num5; i++)
							{
								int num6 = (int)(MBRandom.RandomFloat * (float)num4);
								bool flag = false;
								foreach (ItemRosterElement itemRosterElement2 in this.MapEventSettlement.ItemRoster)
								{
									int amount = itemRosterElement2.Amount;
									num6 -= amount;
									if (num6 < 0)
									{
										rosterElement = itemRosterElement2.EquipmentElement;
										int num7 = (int)(MBRandom.RandomFloat * (float)num3);
										foreach (MapEventParty mapEventParty2 in this.AttackerSide.Parties)
										{
											num7 -= mapEventParty2.Party.MemberRoster.TotalManCount;
											if (num7 < 0)
											{
												partyBase = mapEventParty2.Party;
												flag = true;
												break;
											}
										}
									}
									if (flag)
									{
										break;
									}
								}
								if (!rosterElement.IsEqualTo(EquipmentElement.Invalid))
								{
									this.MapEventSettlement.ItemRoster.AddToCounts(rosterElement, -1);
									if (this._lootedItemCount % 2 == 1)
									{
										int num8 = 1;
										if (rosterElement.Item.IsFood)
										{
											Hero leaderHero2 = partyBase.LeaderHero;
											if (leaderHero2 != null && leaderHero2.GetPerkValue(DefaultPerks.Steward.EfficientCampaigner))
											{
												num8++;
											}
										}
										partyBase.ItemRoster.AddToCounts(rosterElement, num8);
										itemRoster.AddToCounts(rosterElement, num8);
									}
									this._lootedItemCount++;
									num4--;
									rosterElement = EquipmentElement.Invalid;
								}
							}
						}
						foreach (ValueTuple<ItemObject, float> valueTuple in this.MapEventSettlement.Village.VillageType.Productions)
						{
							if ((this.MapEventSettlement.Village.VillageType.PrimaryProduction == DefaultItems.Grain && valueTuple.Item1 == DefaultItems.Grain) || valueTuple.Item1 != DefaultItems.Grain)
							{
								float item = valueTuple.Item2;
								float num9 = num * item / 60f;
								float num10;
								if (this._raidProductionRewards.TryGetValue(valueTuple.Item1, out num10))
								{
									this._raidProductionRewards[valueTuple.Item1] = num10 + num9;
								}
								else
								{
									this._raidProductionRewards.Add(valueTuple.Item1, num9);
								}
								if (this._raidProductionRewards[valueTuple.Item1] >= 1f)
								{
									int num11 = (int)this._raidProductionRewards[valueTuple.Item1];
									this._raidProductionRewards[valueTuple.Item1] = this._raidProductionRewards[valueTuple.Item1] - (float)num11;
									this.LootItemInRaid(this.AttackerSide.LeaderParty, valueTuple.Item1, num11, ref itemRoster);
								}
							}
						}
						for (int j = 0; j < (int)num; j++)
						{
							if (MBRandom.RandomFloat < 0.25f)
							{
								ItemObject item2 = MBRandom.ChooseWeighted<ItemObject>(Campaign.Current.Models.RaidModel.GetCommonLootItemScores());
								this.LootItemInRaid(this.AttackerSide.LeaderParty, item2, 1, ref itemRoster);
							}
						}
						if (itemRoster.Any<ItemRosterElement>() && ((partyBase != null) ? partyBase.MobileParty : null) != null)
						{
							CampaignEventDispatcher.Instance.OnItemsLooted(partyBase.MobileParty, itemRoster);
						}
					}
					if (this.MapEventSettlement.SettlementHitPoints <= 1E-05f)
					{
						this.MapEventSettlement.SettlementHitPoints = 0f;
						base.MapEvent.BattleState = BattleState.AttackerVictory;
						finish = true;
						this.MapEventSettlement.Party.SetLevelMaskIsDirty();
					}
					this._nextSettlementDamage = 0f;
					return;
				}
			}
			else if (this.AttackerSide.TroopCount == 0)
			{
				finish = true;
			}
		}

		// Token: 0x060029A5 RID: 10661 RVA: 0x000B3104 File Offset: 0x000B1304
		internal override void OnAfterLoad()
		{
			if (this._raidProductionRewards == null)
			{
				this._raidProductionRewards = new Dictionary<ItemObject, float>();
			}
		}

		// Token: 0x060029A6 RID: 10662 RVA: 0x000B311C File Offset: 0x000B131C
		private void LootItemInRaid(PartyBase party, ItemObject item, int count, ref ItemRoster lootedItems)
		{
			if (item.IsFood)
			{
				MobileParty mobileParty = party.MobileParty;
				if (mobileParty != null && mobileParty.HasPerk(DefaultPerks.Steward.EfficientCampaigner, false))
				{
					count++;
				}
			}
			lootedItems.AddToCounts(item, count);
			party.ItemRoster.AddToCounts(item, count);
		}

		// Token: 0x04000C86 RID: 3206
		[SaveableField(10)]
		private float _nextSettlementDamage;

		// Token: 0x04000C88 RID: 3208
		[SaveableField(30)]
		private int _lootedItemCount;

		// Token: 0x04000C89 RID: 3209
		[SaveableField(40)]
		private Dictionary<ItemObject, float> _raidProductionRewards = new Dictionary<ItemObject, float>();
	}
}
